#include "sqlite3.hpp"
#include "../platform/include/platform.hpp"
#include "../app/app.hpp"

cache_mem com;

int sqlite_common_callback(void* data,int argc,char** argv,char** Col){ //简单打印查询信息
    for(int i = 0 ; i < argc ; i++){
        std::cout << argv[i] << std::endl;
    }
    return 0;
}

void Sqlite3::init(){
    try{
        int ret = sqlite3_open(db_path,&database);
        if(ret < 0)
            throw sqlite3_errstr(ret);
        
    }catch(const char* error){
        std::cout << "db name: " << db_path <<" error: " << error << std::endl;
    }
}

void Sqlite3::sql(const char* _sql){
    try{
        char* errmsg;
        std::cout << _sql << std::endl;
        int ret = sqlite3_exec(database,_sql,NULL,NULL,&errmsg);
        if(ret != 0)
            throw errmsg;
    }catch(char* e){
        std::cout << e << std::endl;
    }
}

Sqlite3::~Sqlite3(){
    sqlite3_close(database); //关闭数据库
}

void Sqlite3::find(const char* _sql){
    try{
        char* errMsg;
        int ret = sqlite3_exec(database,_sql,callback,NULL,&errMsg);
        if(ret != 0)
            throw errMsg;
    }catch(char* e){
        std::cout << e << std::endl;
    }
}

void Sqlite3::update_callback(sqlite3_callback call){
    this->callback = call; //重新更新callback的调用操作
}

void Sqlite3::operator()(const char* p,const char* n){
    this->db_path = p;
    this->db_table = n;
}

static int check_tab_callback(void *buf,int argc,char** argv,char** Col)
{
    if(argc&0x1){   
        if(buf)
            *((int*)buf) = (int)strtol(*argv,NULL,16); //返回相应的查询状态
    }
    return 0;
}

bool Sqlite3::check_tab(std::string tab){
    std::string check_sql = "SELECT count(*) FROM sqlite_master WHERE type='table' AND name =";
    check_sql += "\"";
    check_sql += std::string(this->db_table);
    check_sql += "\"";

    int st = 0; //sqlite3 中查询数据表是否存在
    char* errMsg;
    int ret = sqlite3_exec(database,check_sql.c_str(),check_tab_callback,(int*)&st,&errMsg);

    if(ret < 0){
        std::cout << errMsg << std::endl;
        exit(1); //程序退出
    }

    return st? true : false;
}

void cache_layer_init(char* tmp,int page_index){
       int i = 0;
       char* ptr = nullptr;
       char t[6][256] = {0}; //FIXME: 这个是根据创建的数据模型,暂时使用的缓存
       while((ptr = strsep(&tmp,",")) != nullptr){
           if( i > 6){
                std::cout << "over pages save" << std::endl; //超出访问页的边界
                break;
           }
            memcpy((char*)t[i++],ptr,strlen(ptr));
       }
       com.pages[page_index].mem_status = CACHE_FIRST_CREATE;
       com.pages[page_index].id = (int)strtol(t[0],NULL,16);
       memcpy(com.pages[page_index].name,(char*)t[1],sizeof(com.pages[page_index].name));
       memcpy(com.pages[page_index].value,(char*)t[2],sizeof(com.pages[page_index].value));
       memcpy(com.pages[page_index].type,(char*)t[3],sizeof(com.pages[page_index].type));
       com.pages[page_index].mode = (unsigned char)strtol(t[4],NULL,16);
       com.pages[page_index].attr = (unsigned char)strtol(t[5],NULL,16);
}

bool parse_config2sqlite(const char* path,Sqlite3& sqlite){
    FILE* fp = fopen(path,"r");
    bool tb_head = false;
    bool tb_first = false;
    file_attr attr(path);
    char tmp[256]; //1行的数据一般情况下不会超过256个字节
    exception_linux error;
    std::string sql_in;
    int i = 0,j = 0;
    int pages_cnt = 0;
    try
    {
        if(!fp)
            throw error;

        while(!feof(fp)){
            fgets(tmp,sizeof(tmp),fp);
            tmp[strlen(tmp)-1] = (tmp[strlen(tmp)-1] == '\n')?'\0':tmp[strlen(tmp)-1]; //去除换行符
          
            if(tmp[0] == '#' || tmp[0] == 0)  //可以在配置文件中进行注释,注释的文件不会在写入数据库,空字符直接下一行
                continue;

            if(!tb_head){
                sql_in = "CREATE TABLE ";
                sql_in += sqlite.tb_name();
                sql_in += "(";
                sql_in += std::string(tmp);
                sql_in += ");";
                sqlite.sql(sql_in.c_str());
                tb_head = true;               
            }else{
                sql_in = "INSERT INTO ";
                sql_in += sqlite.tb_name();
                sql_in += " VALUES";
                sql_in += "(";
                sql_in += std::string(tmp);
                sql_in += ");";
                sqlite.sql(sql_in.c_str());
            }

            sql_in.clear();

            cache_layer_init((char*)tmp,pages_cnt);
            com.full_pages[pages_cnt] = &com.pages[pages_cnt]; //映射到填写的页的空间内,应用开始时去读满页
            pages_cnt++;
            memset(tmp,0,sizeof(tmp));
        }

        for( i = pages_cnt+1, j = 0 ; i <= (int)MAX_PAGES ; i++,j++){ 
            com.empty_pages[j] = &com.pages[i];
        }
        com.end_pages_full_index = pages_cnt;               //初始化记录满页的最终位置
        com.begin_pages_empty_index = pages_cnt+1;          //初始化记录空页的其实地址,记录的原页的起始地址
    }
    catch(const exception_linux& e) //抛出异常必然会对对象进行析构
    {
       ERR("cache layer create:");
       fclose(fp);
    }
    fclose(fp);
    return true;
}

bool update_parse_config(const char* path,Sqlite3& sqlite){
    return true;
}

void Sqlite3::config(std::string file){
    if(parse_config2sqlite(file.c_str(),*this))
        ; //创建缓冲层
    else
        ; //创建缓冲层失败 退出主线程
}

void Sqlite3::update_sqlite(std::string file){
    if(update_parse_config(file.c_str(),*this))
         ;  //从数据库读出数据创建缓冲层
    else
        ;   //建立缓冲层失败 退出主线程

}

std::string Sqlite3::tb_name(){
    return this->db_table;
}